package com.foftact.etf;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.foftact.etf.mapper.ETFListMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ETF基金行情服务实现类
 * 实现ETFListService接口中的业务方法
 */
@Service
public class ETFListServiceImpl implements ETFListService {
    private static final Logger logger = LoggerFactory.getLogger(ETFListServiceImpl.class);

    @Autowired
    private ETFListMapper etfListMapper;

    // ETF基金行情API接口模板（支持分页）
    private static final String ETF_LIST_API_TEMPLATE = "https://push2.eastmoney.com/api/qt/clist/get?np=1&fltt=1&invt=2&cb=jQuery3710020228058951586414&fs=b%3AMK0021%2Cb%3AMK0022%2Cb%3AMK0023%2Cb%3AMK0024%2Cb%3AMK0827&fields=f12%2Cf13%2Cf14%2Cf1%2Cf2%2Cf4%2Cf3%2Cf152%2Cf5%2Cf6%2Cf17%2Cf18%2Cf15%2Cf16&fid=f3&pn={pn}&pz=20&po=1&dect=1&ut=fa5fd1943c7b386f172d6893dbfba10b&wbp2u=%7C0%7C0%7C0%7Cweb&_={timestamp}";

    // 数据来源标识
    private static final String DATA_SOURCE = "东方财富";

    /**
     * 从API抓取并保存ETF基金行情数据（支持分页抓取所有数据）
     * @return 成功保存的记录数
     */
    @Override
    @Transactional
    public int fetchAndSaveETFListData() {
        logger.info("开始抓取ETF基金行情数据");
        try {
            // 先清空现有数据，确保数据的一致性
            clearETFList();
            
            List<ETFList> allETFList = new ArrayList<>();
            int currentPage = 1;
            int totalPages = 1; // 初始化为1，后续会从API响应中获取真实值
            int pageSize = 20;
            
            while (currentPage <= totalPages) {
                logger.info("抓取第{}页ETF数据", currentPage);
                
                // 从API获取当前页数据
                String jsonData = fetchETFDataFromApi(currentPage);
                if (jsonData == null || jsonData.isEmpty()) {
                    logger.error("未获取到第{}页ETF基金行情数据", currentPage);
                    currentPage++;
                    continue;
                }

                // 解析JSON数据和总页数
                ETFListResponseDTO responseDTO = JSON.parseObject(jsonData, ETFListResponseDTO.class, JSONReader.Feature.AllowUnQuotedFieldNames);
                if (responseDTO != null && responseDTO.getRc() == 0 && responseDTO.getData() != null) {
                    // 更新总页数
                    int totalRecords = responseDTO.getData().getTotal();
                    totalPages = (int) Math.ceil((double) totalRecords / pageSize);
                    logger.info("ETF数据总条数：{}, 总页数：{}, 当前迭代：{}", totalRecords, totalPages, currentPage);
                    
                    // 解析当前页数据
                    List<ETFList> currentPageData = parseETFData(jsonData);
                    if (currentPageData != null && !currentPageData.isEmpty()) {
                        allETFList.addAll(currentPageData);
                    }
                }
                
                // 避免请求过快，添加适当延迟
                Thread.sleep(500);
                
                currentPage++;
            }

            // 批量保存所有数据
            if (!allETFList.isEmpty()) {
                int savedCount = batchSaveETFList(allETFList);
                logger.info("ETF基金行情数据抓取完成，共抓取并保存{}条记录", savedCount);
                return savedCount;
            } else {
                logger.error("未抓取到任何ETF基金行情数据");
                return 0;
            }
        } catch (Exception e) {
            logger.error("抓取ETF基金行情数据异常", e);
            throw new RuntimeException("抓取ETF基金行情数据异常", e);
        }
    }

    /**
     * 从API获取指定页码的ETF数据
     * @param pageNum 页码
     * @return JSON格式的数据字符串
     */
    private String fetchETFDataFromApi(int pageNum) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 生成带时间戳的URL，避免缓存
        long timestamp = System.currentTimeMillis();
        String url = ETF_LIST_API_TEMPLATE;
        url = StringUtils.replace(url, "{pn}", String.valueOf(pageNum));
        url = StringUtils.replace(url, "{timestamp}", String.valueOf(timestamp));
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
        httpGet.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
        httpGet.addHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");

        try {
            CloseableHttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                // 去除JSONP的回调函数包装
//                Pattern pattern = Pattern.compile("^\\w+\\((.*)\\)$");
//                Matcher matcher = pattern.matcher(result);
//                if (matcher.find()) {
//                    return matcher.group(1);
//                }
                return StringUtils.substringBetween(result, "(", ")");
            }
        } catch (IOException e) {
            logger.error("调用ETF基金行情API异常，页码：{}", pageNum, e);
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("关闭HTTP客户端异常", e);
            }
        }
        return null;
    }

    /**
     * 解析ETF数据
     * @param jsonData JSON格式的数据字符串
     * @return ETF数据列表
     */
    private List<ETFList> parseETFData(String jsonData) {
        List<ETFList> etfListList = new ArrayList<>();

        try {
            ETFListResponseDTO responseDTO = JSON.parseObject(jsonData, ETFListResponseDTO.class, JSONReader.Feature.AllowUnQuotedFieldNames);
            if (responseDTO != null && responseDTO.getRc() == 0 && responseDTO.getData() != null) {
                List<ETFListDTO> diffList = responseDTO.getData().getDiff();
                if (diffList != null && !diffList.isEmpty()) {
                    for (ETFListDTO dto : diffList) {
                        ETFList etfList = convertToModel(dto);
                        etfListList.add(etfList);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("解析ETF数据异常", e);
        }

        return etfListList;
    }

    /**
     * 将DTO对象转换为Model对象
     * @param dto ETFListDTO对象
     * @return ETFList对象
     */
    private ETFList convertToModel(ETFListDTO dto) {
        ETFList etfList = new ETFList();
        etfList.setCode(dto.getF12());
        etfList.setName(dto.getF14());
        etfList.setLatestPrice(dto.getF2());
        etfList.setPriceChange(dto.getF4());
        etfList.setChangePercent(dto.getF3());
        etfList.setVolume(dto.getF5());
        etfList.setAmount(dto.getF6());
        etfList.setOpenPrice(dto.getF17());
        etfList.setHighPrice(dto.getF15());
        etfList.setLowPrice(dto.getF16());
        etfList.setPrevClosePrice(dto.getF18());
        etfList.setDataSource(DATA_SOURCE);
        return etfList;
    }

    /**
     * 根据基金代码获取ETF数据
     * @param code 基金代码
     * @return ETF数据对象
     */
    @Override
    public ETFList getETFByCode(String code) {
        try {
            return etfListMapper.selectByCode(code);
        } catch (Exception e) {
            logger.error("根据基金代码获取ETF数据异常，code: {}", code, e);
            return null;
        }
    }

    /**
     * 获取所有ETF数据
     * @return ETF数据列表
     */
    @Override
    public List<ETFList> getAllETFList() {
        try {
            return etfListMapper.selectAll();
        } catch (Exception e) {
            logger.error("获取所有ETF数据异常", e);
            return new ArrayList<>();
        }
    }

    /**
     * 保存单个ETF数据
     * @param etfList ETF数据对象
     * @return 保存是否成功
     */
    @Override
    @Transactional
    public boolean saveETFList(ETFList etfList) {
        try {
            int result = etfListMapper.insert(etfList);
            return result > 0;
        } catch (Exception e) {
            logger.error("保存ETF数据异常", e);
            return false;
        }
    }

    /**
     * 批量保存ETF数据
     * @param etfListList ETF数据列表
     * @return 保存的记录数
     */
    @Override
    @Transactional
    public int batchSaveETFList(List<ETFList> etfListList) {
        try {
            int totalCount = 0;
            int batchSize = 50; // 每批处理50个数据

            for (int i = 0; i < etfListList.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, etfListList.size());
                List<ETFList> subList = etfListList.subList(i, endIndex);
                int batchResult = etfListMapper.batchInsert(subList);
                totalCount += batchResult;
            }

            return totalCount;
        } catch (Exception e) {
            logger.error("批量保存ETF数据异常", e);
            return 0;
        }
    }

    /**
     * 更新ETF数据
     * @param etfList ETF数据对象
     * @return 更新是否成功
     */
    @Override
    @Transactional
    public boolean updateETFList(ETFList etfList) {
        try {
            int result = etfListMapper.updateByCode(etfList);
            return result > 0;
        } catch (Exception e) {
            logger.error("更新ETF数据异常", e);
            return false;
        }
    }

    /**
     * 根据基金代码删除ETF数据
     * @param code 基金代码
     * @return 删除是否成功
     */
    @Override
    @Transactional
    public boolean deleteETFByCode(String code) {
        try {
            int result = etfListMapper.deleteByCode(code);
            return result > 0;
        } catch (Exception e) {
            logger.error("删除ETF数据异常，code: {}", code, e);
            return false;
        }
    }

    /**
     * 清空ETF表
     * @return 操作是否成功
     */
    @Override
    @Transactional
    public boolean clearETFList() {
        etfListMapper.truncateTable();
        return true;
    }
}